package com.auxgroup.hr.front.service.process.impl;

import com.alibaba.fastjson.JSON;
import com.auxgroup.hr.front.commons.utils.DateUtils;
import com.auxgroup.hr.front.commons.utils.ObjectFieldUtils;
import com.auxgroup.hr.front.commons.vo.UserDTO;
import com.auxgroup.hr.front.dao.domain.PsCWfPlaveHdr;
import com.auxgroup.hr.front.dao.domain.Psxlatitem;
import com.auxgroup.hr.front.dao.repository.PsCLeaveTblRepository;
import com.auxgroup.hr.front.dao.repository.PsCWfPlaveHdrRepository;
import com.auxgroup.hr.front.dozer.IObjectMapper;
import com.auxgroup.hr.front.hrverify.AuxCheckRequest;
import com.auxgroup.hr.front.hrverify.AuxCheckResponse;
import com.auxgroup.hr.front.service.comm.SysDictService;
import com.auxgroup.hr.front.service.process.WfFileService;
import com.auxgroup.hr.front.service.process.WfPlaveHdrService;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 请假销假服务
 *
 * @author lvliuhao
 * @version 创建时间：2018年7月20日 下午4:55:28
 * 类说明
 */
@Service("wfPlaveHdrService")
public class WfPlaveHdrServiceImpl implements WfPlaveHdrService {
    private static final Logger logger = LoggerFactory.getLogger(WfPlaveHdrServiceImpl.class);

    @Autowired
    private PsCWfPlaveHdrRepository psCWfPlaveHdrRepository;

    @Autowired
    private PsCLeaveTblRepository psCLeaveTblRepository;

    @Autowired
    private WfInitServiceImpl wfInitService;

    @Autowired
    private WfFileService wfFileService;

    @Resource(name = "dozerMapper")
    protected IObjectMapper objectMapper;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    protected SysDictService sysDictService;

    @Value("${auxgroup.hr.business.procUrl}")
    private String procUrl;


    @Override
    public List<PsCWfPlaveHdr> querySaveds(String emplid, String keywords) {
        Specification<PsCWfPlaveHdr> spec = (root, query, builder) -> {
            Predicate cWfStatus = builder.equal(root.get("cWfStatus"), "S");
            builder.and(builder.equal(root.get("cWfEmplid"), emplid));
            if (StringUtils.isNotBlank(keywords)) {
                return builder.and(cWfStatus, builder.like(root.get("cTransactionNbr"), "%" + keywords + "%"));
            }
            return builder.and(cWfStatus);
        };
        return psCWfPlaveHdrRepository.findAll(spec, new Sort(Sort.Direction.DESC, "startDate"));
    }

    @Override
    public BigDecimal calcApplyPregnantTime(String emplid, Date startDate, String pregnantTime) {
        //申请中产检假天数
        BigDecimal applyingPregnantDay = new BigDecimal(0);
        //申请成功的产检假天数
        BigDecimal appliedPregnantDay = new BigDecimal(0);

        List applyingPregnantList = psCWfPlaveHdrRepository.countApplyingPregnantDays("P", pregnantTime, startDate, emplid);
        if (applyingPregnantList != null && applyingPregnantList.size() > 0 && applyingPregnantList.get(0) != null) {
            applyingPregnantDay = (BigDecimal) applyingPregnantList.get(0);
        }

        List appliedPregnantList = psCLeaveTblRepository.countAppliedPregnantDays(pregnantTime, startDate, emplid);
        if (appliedPregnantList != null && appliedPregnantList.size() > 0 && appliedPregnantList.get(0) != null) {
            appliedPregnantDay = (BigDecimal) appliedPregnantList.get(0);
        }

        return appliedPregnantDay.add(applyingPregnantDay);
    }

    @Override
    public String valide(PsCWfPlaveHdr laveReq, UserDTO user) {

        if ("L90".equals(laveReq.getcLeaveType())) {
            //如果为哺乳假
            AuxCheckRequest valReq = new AuxCheckRequest("udp_AuxBRQjCheck");
            valReq.add("EmpNo", user.getEmplId());

            valReq.add("BDate", DateUtils.format(new Date(), "yyyy-MM-dd"))
                    .add("EDate", handleBrqjDate(laveReq.getBirthdate()))
                    .add("AddDay", DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"))
                    .add("BillNo", laveReq.getcTransactionNbr())
                    .add("QJArg", transformLeaveCycleValue(laveReq.getcLeaveCycle()));
            AuxCheckResponse resp = restTemplate.postForObject(procUrl, valReq, AuxCheckResponse.class);
            logger.info("HR 校验{}", JSON.toJSONString(resp));
            return resp.getValue("@returnvalue");
        } else {
            AuxCheckRequest valReq = new AuxCheckRequest("udp_AuxMAPQjCheck");
            valReq.add("EmpNo", user.getEmplId());

            valReq.add("BillNo", laveReq.getcTransactionNbr())
                    .add("BillType", getDictValue("C_LEAVE_TYPE", laveReq.getcLeaveType()))
                    .add("AddDay", DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"))
                    .add("Reason", laveReq.getcApplInfo())
                    .add("IsKT", laveReq.getcAcrossDay())
                    .add("BDate", DateUtils.format(laveReq.getStartDate(), "yyyy-MM-dd"));
            if (laveReq.getcAcrossDay().equals("Y")) {
                valReq.add("BDateQJArg", transformLeaDay(laveReq.getcLeaDay2()));
                valReq.add("EDate", DateUtils.format(laveReq.getEndDate(), "yyyy-MM-dd"));
                valReq.add("EDateQJArg", transformLeaDay(laveReq.getcLeaDay3()));
            } else {
                valReq.add("BDateQJArg", transformLeaDay(laveReq.getcLeaDay1()));
                valReq.add("EDate", "");
                valReq.add("EDateQJArg", "");
            }
            AuxCheckResponse resp = restTemplate.postForObject(procUrl, valReq, AuxCheckResponse.class);
            logger.info("HR 校验{}", JSON.toJSONString(resp));
            return resp.getValue("@returnvalue");
        }
    }

    public static String doRestPost(String url, String param) {

        HttpClient client = getHttpClient();

        StringEntity entity = null;
        HttpPost post = new HttpPost(url);
        // ResponseHandler<String> responseHandler = new BasicResponseHandler();
        String responseJson = null;
        try {
            entity = new StringEntity(param, "utf-8");
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            post.setEntity(entity);
            HttpResponse response = client.execute(post);
            responseJson = EntityUtils.toString(response.getEntity());

        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return responseJson;

    }

    private static CloseableHttpClient httpClient = null;

    public static HttpClient getHttpClient() {
        if (httpClient == null) {
            httpClient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();

        }
        return httpClient;
    }

    protected String getDictValue(String fieldName, String fileValue) {
        if (StringUtils.isEmpty(fileValue)) {
            return null;
        }
        Psxlatitem item = sysDictService.getSysDict(fieldName, fileValue);
        if (item != null) {
            return item.getXlatshortname();
        }
        return null;
    }

    /**
     * 时段
     * 转换为考勤对应值
     * 上半天 A 1
     * 下半天 B 2
     * 全天 C 3
     *
     * @param cLeaDay2
     * @return
     */
    private String transformLeaDay(String cLeaDay2) {
        switch (cLeaDay2) {
            case "A":
                return "1";
            case "B":
                return "2";
            case "C":
                return "3";
        }
        return "0";
    }

    /**
     * 请假周期
     * 转换为考勤对应值
     * A 1 早上一小时
     * N 2 中午一小时
     * P 3 下午一小时
     * M 4 早晚各半小时
     *
     * @param cLeaveCycle
     * @return
     */
    private String transformLeaveCycleValue(String cLeaveCycle) {

        switch (cLeaveCycle) {
            case "A":
                return "1";
            case "N":
                return "2";
            case "P":
                return "3";
            case "M":
                return "4";
        }
        return "0";
    }

    /**
     * 哺乳假天数
     *
     * @param birthdate 宝宝出生日期加一年减一天
     * @return
     */
    private String handleBrqjDate(Date birthdate) {

        Calendar c = Calendar.getInstance();
        c.setTime(birthdate);
        c.add(Calendar.YEAR, 1);
        c.add(Calendar.DATE, -1);
        return DateUtils.format(c.getTime(), "yyyy-MM-dd");
    }


    @Override
    public PsCWfPlaveHdr getWfInfo(String transNum) {
        return psCWfPlaveHdrRepository.findOne(transNum);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PsCWfPlaveHdr saveWfInfo(PsCWfPlaveHdr plave, UserDTO user) {
        PsCWfPlaveHdr laveHdr = psCWfPlaveHdrRepository.findOne(plave.getcTransactionNbr());
        if (laveHdr == null) {
            laveHdr = wfInitService.init(new PsCWfPlaveHdr(), user, plave.getcTransactionNbr());
            //FIXME
//			laveHdr.setcOtherExplain(plave.getcApplInfo());
        }
        laveHdr.baseInit(plave);
        laveHdr.setLastupdoprid(user.getOprId()); // 更新者
        laveHdr.setLastupddttm(new Timestamp(System.currentTimeMillis())); // 更新时间
        ObjectFieldUtils.handleNullValue(laveHdr);
        return psCWfPlaveHdrRepository.save(laveHdr);
    }

    @Override
    public void delWfInfo(String transNum) {
        wfFileService.delWfFiles(transNum, true);
        psCWfPlaveHdrRepository.deleteByTransNum(transNum);
    }

}
 